using RuoVea.ExPws;
using RuoVea.OmiApi.Config.Service;
using RuoVea.OmiApi.UserRoleMenu.Entitys;

namespace RuoVea.OmiApi.UserRoleMenu.Service;

/// <summary>
/// 系统用户服务 🔷
/// </summary>
[ApiExplorerSettings(GroupName = "system")]
public class SysUserService : IApplicationService
{
    private readonly IPasswordServer _passwordServer;
    private readonly ICurrentUser _currentUser;
    private readonly SysUserRoleService _sysUserRoleService;
    private readonly SysConfigService _sysConfigService;
    private readonly SysCacheService _sysCacheService;
    private readonly SugarRepository<SysUser> _sysUserRep;
    /// <summary>
    /// 
    /// </summary>
    /// <param name="currentUser"></param>
    /// <param name="sysUserRoleService"></param>
    /// <param name="sysConfigService"></param>
    /// <param name="sysCacheService"></param>
    /// <param name="sysUserRep"></param>
    /// <param name="passwordServer"></param>
    public SysUserService(ICurrentUser currentUser, SysUserRoleService sysUserRoleService, SysConfigService sysConfigService, SysCacheService sysCacheService, SugarRepository<SysUser> sysUserRep, IPasswordServer passwordServer)
    {
        _currentUser = currentUser;
        _sysUserRoleService = sysUserRoleService;
        _sysConfigService = sysConfigService;
        _sysCacheService = sysCacheService;
        _sysUserRep = sysUserRep;
        _passwordServer = passwordServer;
    }

    /// <summary>
    /// 根据用户Id获取用户
    /// </summary>
    /// <param name="userId"></param>
    /// <returns></returns>
    public async Task<SysUser> GetUserById(long userId)
    {
        return await _sysUserRep.GetFirstAsync(u => u.Id == userId);
    }

    /// <summary>
    /// 获取用户分页列表 🔹
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("获取用户分页列表")]
    public virtual async Task<PageResult<UserOutput>> Page(PageUserInput input)
    {
        return await _sysUserRep.AsQueryable()
            //.LeftJoin<SysOrganization>((u, a) => u.OrgId == a.Id)
            //.LeftJoin<SysPosition>((u, a, b) => u.PosId == b.Id)
            .Where((u) => u.AdminType != AdminType.SuperAdmin)
            .WhereIF(!string.IsNullOrWhiteSpace(input.Account), u => u.Account.Contains(input.Account))
            .WhereIF(!string.IsNullOrWhiteSpace(input.RealName), u => u.RealName.Contains(input.RealName))
            //.WhereIF(!string.IsNullOrWhiteSpace(input.PosName), (u, a, b) => b.Name.Contains(input.PosName))
            .WhereIF(!string.IsNullOrWhiteSpace(input.Phone), u => u.Phone.Contains(input.Phone))
            .OrderBy((u) => new { u.Id })
            .Select((u) => new UserOutput
            {
                RoleName = SqlFunc.Subqueryable<SysUserRole>().LeftJoin<SysRole>((m, n) => m.RoleId == n.Id).Where(m => m.UserId == u.Id).SelectStringJoin((m, n) => n.Name, ","),
            }, true)
            .ToPageAsync(input.PageNo, input.PageSize);
    }

    /// <summary>
    /// 获取角色用户相关信息 
    /// </summary>
    /// <param name="roleId"></param>
    /// <returns></returns>
    public async Task<List<UserOutput>> GetRoleUserListByRoleId(long roleId)
    {
        var data = await _sysUserRep
    .Context.Queryable<SysUserRole, SysUser>((a, b) => a.UserId == b.Id)
       .Where((a, b) => b.AdminType != AdminType.SuperAdmin)
       .Where((a, b) => a.RoleId == roleId && b.IsDisable == YesOrNot.N)
       .Select((a, b) => new UserOutput
       {
           Id = a.UserId,
           Account = b.Account,
           NickName = b.NickName,
           RealName = b.RealName
       }).ToListAsync();
        return data;
    }
    /// <summary>
    /// 获取用户列表 🔹
    /// </summary>
    /// <returns></returns>
    [DisplayName("获取用户列表")]
    public virtual async Task<List<UserOutput>> UserList()
    {
        return await _sysUserRep.AsQueryable()
            .Where((u) => u.AdminType != AdminType.SuperAdmin)
            .OrderBy((u) => new { u.Id })
            .Select((u) => new UserOutput { }, true)
            .ToListAsync();
    }
    /// <summary>
    /// 增加用户 🔹
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [UnitOfWork]
    [HttpPost("Add"),]
    [DisplayName("增加用户")]
    public virtual async Task<long> AddUser(AddUserInput input)
    {
        var isExist = await _sysUserRep.AsQueryable().ClearFilter().AnyAsync(u => u.Account == input.Account);
        if (isExist) throw new AggregateException(i18n.account_exists);

        var user = input.Adapt<SysUser>();
        if (input.Password.IsNullOrWhiteSpace())
        {
            var password = await _sysConfigService.GetDefault_Password();
            user.Password = _passwordServer.Decrypt(password.ToMD5Encrypt());
        }
        var newUser = await _sysUserRep.AsInsertable(user).ExecuteReturnEntityAsync();

        input.Id = newUser.Id;
        await UpdateRoleAndExtOrg(input);

        return newUser.Id;
    }

    /// <summary>
    /// 更新用户 🔹
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [UnitOfWork]
    [HttpPut("Update"),]
    [DisplayName("更新用户")]
    public virtual async Task UpdateUser(UpdateUserInput input)
    {
        if (await _sysUserRep.AsQueryable().ClearFilter().AnyAsync(u => u.Account == input.Account && u.Id != input.Id))
            throw new AggregateException(i18n.account_exists);

        await _sysUserRep.AsUpdateable(input.Adapt<SysUser>()).IgnoreColumns(true)
            .IgnoreColumns(u => new { u.Password, u.IsDisable }).ExecuteCommandAsync();

        await UpdateRoleAndExtOrg(input);

        // 若账号的角色和组织架构发生变化,则强制下线账号进行权限更新
        var user = await _sysUserRep.AsQueryable().ClearFilter().FirstAsync(u => u.Id == input.Id);
        var roleIds = await GetOwnRoleList(input.Id);
    }

    /// <summary>
    /// 更新角色和扩展机构
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    private async Task UpdateRoleAndExtOrg(AddUserInput input)
    {
        await GrantRole(new UserRolesInput { UserId = input.Id, RoleIdList = input.RoleIdList });
    }

    /// <summary>
    /// 删除用户 🔹
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [UnitOfWork]
    [HttpDelete("Delete"),]
    [DisplayName("删除用户")]
    public virtual async Task DeleteUser(DeleteUserInput input)
    {
        var user = await _sysUserRep.GetByIdAsync(input.Id) ?? throw new AggregateException(i18n.account_not_exists);

        if (user.AdminType == AdminType.SuperAdmin)
            throw new AggregateException(i18n.prohibit_delete_super_admin);

        if (user.Id == _currentUser.UserId)
            throw new AggregateException(i18n.illegal_operation_self);

        await _sysUserRep.DeleteAsync(user);

        // 删除用户角色
        await _sysUserRoleService.DeleteUserRoleByUserId(input.Id);
    }

    /// <summary>
    /// 查看用户基本信息 🔹
    /// </summary>
    /// <returns></returns>
    [DisplayName("查看用户基本信息")]
    public virtual async Task<SysUser> GetBaseInfo()
    {
        return await _sysUserRep.GetByIdAsync(_currentUser.UserId);
    }

    /// <summary>
    /// 更新用户基本信息 🔹
    /// </summary>
    /// <returns></returns>
    [HttpPut("BaseInfo"),]
    [DisplayName("更新用户基本信息")]
    public virtual async Task<int> UpdateBaseInfo(SysUser user)
    {
        return await _sysUserRep.AsUpdateable(user)
            .IgnoreColumns(u => new { u.CreateTime, u.Account, u.Password, u.AdminType /*, u.OrgId, u.PosId*/ }).ExecuteCommandAsync();
    }

    /// <summary>
    /// 设置用户状态 🔹
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [UnitOfWork]
    [DisplayName("设置用户状态")]
    public virtual async Task<int> SetStatus(UserInput input)
    {
        if (_currentUser.UserId == input.Id)
            throw new AggregateException(i18n.prohibit_modify_self_status);

        var user = await _sysUserRep.GetByIdAsync(input.Id) ?? throw new AggregateException(i18n.account_not_exists);
        if (user.AdminType == AdminType.SuperAdmin)
            throw new AggregateException(i18n.prohibit_modify_super_admin_status);

        if (!input.IsDisable.IsDefined<StatusEnum>())
            throw new AggregateException(i18n.dict_status_error);

        // 账号禁用则增加黑名单，账号启用则移除黑名单
        if (input.IsDisable == YesOrNot.Y)
        {
            _sysCacheService.Set($"{CacheConst.KeyBlacklist}{user.Id}", $"{user.RealName}-{user.Phone}");
        }
        else
        {
            _sysCacheService.Remove($"{CacheConst.KeyBlacklist}{user.Id}");
        }

        user.IsDisable = input.IsDisable;
        return await _sysUserRep.AsUpdateable(user).UpdateColumns(u => new { u.IsDisable }).ExecuteCommandAsync();
    }

    /// <summary>
    /// 授权用户角色 🔹
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [UnitOfWork]
    [DisplayName("授权用户角色")]
    public async Task GrantRole(UserRolesInput input)
    {
        //var user = await _sysUserRep.GetFirstAsync(u => u.Id == input.UserId) ??  throw new AggregateException(i18n.account_not_exists);
        //if (user.AccountType == AccountTypeEnum.IsSuperAdmin)
        //     throw new AggregateException(ErrorEnum.D1022);

        await _sysUserRoleService.GrantUserRoles(input);
    }

    /// <summary>
    /// 修改用户密码 🔹
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("修改用户密码")]
    public virtual async Task<int> ChangePwd(ChangePwdInput input)
    {
        if (input.PasswordOld == input.PasswordNew)
            throw new AggregateException(i18n.new_password_same_as_old);

        var user = await _sysUserRep.GetByIdAsync(_currentUser.UserId) ?? throw new AggregateException(i18n.account_not_exists);

        if (_passwordServer.Validate(input.PasswordOld, user.Password))
            throw new AggregateException(i18n.password_error);

        //// 验证密码强度
        //if (CryptogramUtil.StrongPassword)
        //{
        //    user.Password = input.PasswordNew.TryValidate(CryptogramUtil.PasswordStrengthValidation)
        //        ? CryptogramUtil.Encrypt(input.PasswordNew)
        //        : throw  new AggregateException(CryptogramUtil.PasswordStrengthValidationMsg);
        //}
        //else
        //{
        user.Password = _passwordServer.Encrypt(input.PasswordNew);
        //}

        return await _sysUserRep.AsUpdateable(user).UpdateColumns(u => u.Password).ExecuteCommandAsync();
    }

    /// <summary>
    /// 重置用户密码 🔹
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("重置用户密码")]
    public virtual async Task<string> ResetPwd(ResetPwdUserInput input)
    {
        var user = await _sysUserRep.GetByIdAsync(input.Id) ?? throw new AggregateException(i18n.account_not_exists);
        var password = await _sysConfigService.GetDefault_Password();
        user.Password = _passwordServer.Decrypt(password.ToMD5Encrypt());
        await _sysUserRep.AsUpdateable(user).UpdateColumns(u => u.Password).ExecuteCommandAsync();

        // 清空密码错误次数
        var keyErrorPasswordCount = $"{CacheConst.KeyPasswordErrorTimes}{user.Account}";
        _sysCacheService.Remove(keyErrorPasswordCount);

        return password;
    }

    /// <summary>
    /// 解除登录锁定 🔹
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("解除登录锁定")]
    public virtual async Task UnlockLogin(UnlockLoginInput input)
    {
        var user = await _sysUserRep.GetByIdAsync(input.Id) ?? throw new AggregateException(i18n.account_not_exists);

        // 清空密码错误次数
        var keyPasswordErrorTimes = $"{CacheConst.KeyPasswordErrorTimes}{user.Account}";
        _sysCacheService.Remove(keyPasswordErrorTimes);
    }

    /// <summary>
    /// 获取用户拥有角色集合 🔹
    /// </summary>
    /// <param name="userId"></param>
    /// <returns></returns>
    [DisplayName("获取用户拥有角色集合")]
    public async Task<List<long>> GetOwnRoleList(long userId)
    {
        return await _sysUserRoleService.GetUserRoleIdList(userId);
    }
}